package com.org.khtn.data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.Vector;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.org.khtn.ultilities.Ultilities;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Type;

import javax.swing.text.Utilities;

public class Database {
	/**
	 * Load cÃ¡c database Ä‘Ã£ dc nÃªu á»Ÿ trong file data.json
	 */
	private Gson gson;
	List<Data> myData;
	String dataLocation;
	final String className = "Database:";

	public Database() {
		gson = new Gson();
		myData = new ArrayList<Data>();
		dataLocation = "myTest\\data.json";
	}

	public Database(String DataLocation) {
		gson = new Gson();
		myData = new ArrayList<Data>();
		dataLocation = DataLocation;
	}

	/**
	 * Load data tá»« file data.json
	 * 
	 * @throws IOException
	 *             náº¿u khÃ´ng load dc file
	 */
	public void LoadData() throws IOException {
		final String methodName = "LoadData():";
		Type listOfTestObject = new TypeToken<List<Data>>() {
		}.getType();
		File f = new File(dataLocation);
		if (!f.exists()) {
			f.getParentFile().mkdirs();
			File aaa = new File(f.getParentFile().getCanonicalPath()
					+ "\\data\\temp");
			aaa.mkdirs();
			String tam2 = "[]";
			f.createNewFile();

			FileWriter a = null;
			a = new FileWriter(dataLocation);
			a.write(tam2);
			a.close();

		}
		Reader isReader = new InputStreamReader(new FileInputStream(
				(dataLocation)));
		myData.clear();
		myData = Collections.synchronizedList((List<Data>) gson.fromJson(
				isReader, listOfTestObject));
		System.out.println(className + methodName + "mydata: " + myData);
		isReader.close();

	}

	/**
	 * save xuá»‘ng file
	 */
	public void save(Object data, String dataLocation) {
		Gson gson = new Gson();
		Writer osWriter = null;
		try {
			osWriter = new OutputStreamWriter(
					new FileOutputStream(dataLocation));
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		gson.toJson(data, osWriter);
		try {
			osWriter.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Add thÃªm database vÃ o data.json
	 * 
	 * @param data
	 */
	public void add(Data data) {

		myData.add(data);
		Map<String, Map<String, Map<String, String>>> myData1 = new HashMap<String, Map<String, Map<String, String>>>();
		String tam1 = "{}";
		String tam2 = "[]";
		FileWriter a, b = null;
		try {
			a = new FileWriter("mytest\\data\\" + data.getName() + ".json");
			b = new FileWriter("mytest\\data\\" + data.getName() + ".define");
			b.write(tam2);
			a.write(tam1);
			a.close();
			b.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		save(myData, dataLocation);

	}

	/**
	 * XÃ³a toÃ n bá»™ database
	 */
	public void removeAll() {
		myData.clear();
		save(myData, dataLocation);
	}

	/**
	 * XÃ³a Ä‘á»‘i tÆ°á»£ng data khá»�i list
	 * 
	 * @param data
	 */
	public void removeData(Data data) {
		if (myData.contains(data))
			myData.remove(data);
		save(myData, dataLocation);
	}

	/**
	 * Tráº£ vá»� 1 dÃ²ng record cÃ³ giÃ¡ trá»‹ field báº±ng value cá»§a
	 * tableName cá»§a database name
	 * 
	 * @param databaseName
	 *            tÃªn cá»§a database
	 * @param tableName
	 *            tÃªn cá»§a table
	 * @param fieldName
	 *            tÃªn cá»§a field
	 * @param value
	 *            giÃ¡ trá»‹ cá»§a field
	 * @return kiá»ƒu Map<String,String>
	 */
	public Map<String, Map<String, String>> getRowFromDatabase(
			String databaseName, String tableName, String fieldName,
			String value) {
		DataTables dataTables = new DataTables(getData(databaseName));
		return dataTables.getRow(tableName, fieldName, value);
	}

	/**
	 * Tráº£ vá»� dÃ²ng cÃ³ sá»‘ thá»© tá»± idx cá»§a tableName cá»§a database
	 * name
	 * 
	 * @param databaseName
	 *            tÃªn cá»§a database
	 * @param tableName
	 *            tÃªn cá»§a table
	 * @param idx
	 *            vá»‹ trÃ­ cá»§a record trong table
	 * @return
	 */
	public Map<String, Map<String, String>> getRowFromDatabase(
			String databaseName, String tableName, int idx) {
		DataTables dataTables = new DataTables(getData(databaseName));
		return dataTables.getRow(tableName, idx);
	}

	/**
	 * remove database theo tÃªn
	 * 
	 * @param name
	 *            tÃªn cá»§a database
	 */
	public void removeData(String name) {
		Data temp = getData(name);
		removeData(temp);

		save(myData, dataLocation);
	}

	public void editAllRecord(String databaseName, String tableName,
			String fieldName, String fieldValue) {
		DataTables dataTables = new DataTables(getData(databaseName));
		dataTables.editValueAllRecord(tableName, fieldName, fieldValue);
	}

	/**
	 * Tráº£ vá»� database theo thá»© tá»± index
	 * 
	 * @param index
	 * @return
	 */
	public Data getData(int index) {
		if (index > -1 && index < myData.size()) {
			return (Data) myData.get(index);
		}

		return null;
	}

	/**
	 * TÃ¬m 1 database vá»›i dataName
	 * 
	 * @param dataName
	 *            ten database
	 * @return kiá»ƒu Data
	 */
	public Data getData(String dataName) {
		int length = myData.size();
		for (int i = 0; i < length; i++) {
			if (((Data) myData.get(i)).getName().equals(dataName))
				return (Data) myData.get(i);
		}
		return null;

	}

	public void createTableField(String databaseName, String tableName,
			String fieldName, String fieldType) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.createTableField(tableName, fieldName, fieldType);
	}

	public void editTableFieldType(String databaseName, String tableName,
			String fieldName, String fieldType) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.editTableFieldType(tableName, fieldName, fieldType);

	}

	public Map<String, Vector> getAllDatabase() {
		// TODO Auto-generated method stub
		final String methodName = "getAllDatabase():";
		Map<String, Vector> temp = new HashMap<String, Vector>();
		for (Data d : myData) {
			DataTables dt = new DataTables(getData(d.getName()));
			Vector tableName = dt.getAllTableName();
			temp.put(d.getName(), tableName);
		}
		return temp;
	}

	public Map<String, Map<String, String>> getAllTableRecord(
			String databaseName, String tableName) {
		// TODO Auto-generated method stub

		DataTables dt = new DataTables(getData(databaseName));
		return dt.getAllRow(tableName);

	}

	public void createTable(String databaseName, String tableName) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.createTable(tableName);
	}

	public void removeTable(String databaseName, String tableName) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.removeTable(tableName);
	}

	public void insertRecord(String databaseName, String tableName,
			String[] fieldName, String[] fieldValue) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.insertRecord(tableName, fieldName, fieldValue);

	}

	Map<String, String> getTableDefines(String databaseName, String tableName) {
		// TODO Auto-generated method stub
		// return null;
		DataTables dt = new DataTables(getData(databaseName));
		return dt.getTableDefines(tableName);
	}

	public void editRecord(int idx, String databaseName, String tableName,
			String fieldName, String fieldValue) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.editRecord(idx, tableName, fieldName, fieldValue);
	}

	public void removeTableField(String databaseName, String tableName,
			String fieldName) {
		DataTables dt = new DataTables(getData(databaseName));
		dt.removeTableField(tableName, fieldName);
		// TODO Auto-generated method stub

	}

	public void insertTableField(String databaseName, String tableName,
			String fieldName, String fieldType, boolean dataexist) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.insetTableField(tableName, fieldName, fieldType, dataexist);

	}

	public void removeAllTableField(String databaseName, String tableName) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.removeAllTableField(tableName);

	}

	public void editTableFieldName(String databaseName, String tableName,
			String fieldName, String fieldNameNew) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.editTableFieldName(tableName, fieldName, fieldNameNew);
	}

	/**
	 * Táº¡o file temp cá»§a database .. tÆ°Æ¡ng lai sáº½ back up 1 table thÃ´i
	 * cho nhanh
	 * 
	 * @param databaseName
	 * @return
	 */
	public void createTempDatabase(String databaseName) {
		// TODO Auto-generated method stub
		File f = new File("mytest\\data\\temp\\");
		String sourcejson = "mytest\\data\\" + databaseName + ".json";
		String backupjson = "mytest\\data\\temp\\" + databaseName + ".json";
		String sourceData = "mytest\\data\\" + databaseName + ".define";
		String backupData = "mytest\\data\\temp\\" + databaseName + ".define";

		try {
			Ultilities.CopyFile(sourceData, backupData);
			Ultilities.CopyFile(sourcejson, backupjson);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		}

	}

	public void removeAllTableRecord(String databaseName, String tableName) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.removeAllTableRecord(tableName);
	}

	public void backupDatabase(String databaseName) {
		// TODO Auto-generated method stub
		String defineSource = "mytest\\data\\" + databaseName + ".define";
		String defineBackup = "mytest\\data\\temp\\" + databaseName + ".define";
		String dataSource = "mytest\\data\\" + databaseName + ".json";
		String dataBackup = "mytest\\data\\temp\\" + databaseName + ".json";

		try {
			Ultilities.CopyFile(defineBackup, defineSource);
			Ultilities.CopyFile(dataBackup, dataSource);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		deleteBackupDatabase(databaseName);
	}

	void deleteBackupDatabase(String databaseName) {
		// TODO Auto-generated method stub
		String defineBackup = "mytest\\data\\temp\\" + databaseName + ".define";
		String dataBackup = "mytest\\data\\temp\\" + databaseName + ".json";

		Ultilities.DeleteFile(defineBackup);
		Ultilities.DeleteFile(dataBackup);

	}

	public Vector getAllTableName(String databaseName) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		return dt.getAllTableName();
	}

	public Vector getAllDatabaseName() {
		// TODO Auto-generated method stub
		Vector<String> result = new Vector<String>();
		for (Data d : myData) {
			result.add(d.getName());
		}
		return result;
	}

	public void setTablePrimaryKey(java.lang.String databaseName,
			java.lang.String tableName, Vector keys) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.setTablePrimaryKey(tableName, keys);
	}

	public Vector<java.lang.String> getTablePrimaryKey(
			java.lang.String databaseName, java.lang.String tableName) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		return dt.getTablePrimaryKey(tableName);
	}

	public void removeTablePrimaryKey(java.lang.String databaseName,
			java.lang.String tableName) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.removeTablePrimaryKey(tableName);
	}

	public void deleteTableRecord(java.lang.String databaseName,
			java.lang.String tableName, java.lang.String rowID) {
		// TODO Auto-generated method stub
		DataTables dt = new DataTables(getData(databaseName));
		dt.deleteTableRecord(tableName, rowID);
	}

}